/**
 * Copyright (c) 2007,中企动力华南研发中心<br>
 * All rights reserved.<br>
 */
package com.ce.pms.charge.service.impl;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IChargeStaDao;
import com.ce.pms.charge.dao.IFlowDefDao;
import com.ce.pms.charge.dao.IMeterDataRegisterDao;
import com.ce.pms.charge.dao.INoteDao;
import com.ce.pms.charge.dao.IPeriodDao;
import com.ce.pms.charge.dao.IPeriodLogDao;
import com.ce.pms.charge.model.AbstractStaVersion;
import com.ce.pms.charge.model.ChargeDatasDomain;
import com.ce.pms.charge.model.NoteDomain;
import com.ce.pms.charge.model.PeriodDomain;
import com.ce.pms.charge.model.PeriodLogDomain;
import com.ce.pms.charge.model.SectSta;
import com.ce.pms.charge.model.TransRNote;
import com.ce.pms.charge.service.INoteService;
import com.ce.pms.charge.vo.ManageHouseBankBean;
import com.ce.pms.charge.vo.NoteVO;
import com.ce.pms.charge.vo.TransRNoteVO;
import com.ce.pms.charge.vo.TransrnoteNote;
import com.ce.pms.common.annotation.NoDACL;
import com.ce.pms.common.model.SysInfo;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.common.util.PmsUtilityComparator;
import com.ce.pms.customer.dao.IProRightDao;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.dao.ICoalitionHouseDao;
import com.ce.pms.house.dao.IHouseDao;
import com.ce.pms.house.model.CoalitionHouseDomain;
import com.ce.pms.house.model.HouseDomain;
import com.ce.pms.report.vo.PrintChargeNoteBean;
import com.sitechasia.webx.core.support.Page;

/**
 * 功能描述：收费通知单<br>
 * @author 易贤建 创建日期：2008-9-16<br>
 */
public class NoteServiceImpl extends PmsBaseServiceImpl implements INoteService {
	private final int PAGESIZE=5000;
	private INoteDao noteDao;
	private IHouseDao houseDao;
	private IProRightDao proRightDao;
	private IMeterDataRegisterDao meterDataRegisterDao;
	private IChargeStaDao chargeStaDao;
	private IFlowDefDao flowDefDao;
	private IPeriodLogDao periodLogDao;
	private IPeriodDao periodDao;
	private static final String REQUISITION_NOTE_NUMBER = "SFTZD-";
	private static final String REMINDER_NOTE_NUMBER = "CJD-";
	private ICoalitionHouseDao coalitionHouseDao;

	private final int chargeDataSizeException=10;//异常显示的房号数量

	/**
	 * 功能描述:  根据ID 查询通知单<br>
	 * @param noteId
	 * @return
	 * Create author:yixianjian <br>
	 * Create on:2008-9-18  <br>
	 */
	public NoteVO findNoteById(Long noteId){
		return convertDoToVO(noteDao.findById(noteId));
	}

	/**
	 * 功能描述:  根据通知单ID  查询通知单明细<br>
	 * @param notevo
	 * @return
	 * Create author:yixianjian <br>
	 * Create on:2008-9-18  <br>
	 */
	public Page findTransRNoteByNoteId(NoteVO notevo){
		Page page= noteDao.queryTransRNoteByNoteId(notevo);
		List<TransRNote> result=page.getResult();
		List<TransRNoteVO> temp=new ArrayList<TransRNoteVO>();
		for(TransRNote transRNote : result){
			TransRNoteVO transRNoteVO=new TransRNoteVO();
			transRNoteVO.setChargeItemName(transRNote.getChargeItem().getItemName());
			transRNoteVO.setLastReading(transRNote.getLastReading());
			transRNoteVO.setPrice(transRNote.getPrice());
			transRNoteVO.setTotalAmt(transRNote.getTotalAmt());
			transRNoteVO.setThisReading(transRNote.getThisReading());
			transRNoteVO.setWastage(transRNote.getWastage());
			temp.add(transRNoteVO);
		}
		page.setResult(temp);
		return new Page();
	}

	public Page queryNote(NoteVO searchVO){
		//设置管理房查询条件
		setManageProrightHouseSearchVO(searchVO);
		Page page=noteDao.queryNote(searchVO);
		page.setResult(convertDOtoVOList(page.getResult()));
		return page;
	}

	/**
	 * 功能描述:打印通知单的查询<br>
	 * @param searchVO
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-11-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public List<PrintChargeNoteBean> queryPrintChargeNote(NoteVO searchVO){
		//设置管理房查询条件
		setManageProrightHouseSearchVO(searchVO);
		return noteDao.queryPrintChargeNote(searchVO);
	}

	/** 功能描述:<br>
	 * @param searchVO<br>
	 * Create author:罗军林<br>
	 * Create on:2008-11-11<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void setManageProrightHouseSearchVO(NoteVO searchVO) {
		if(null==searchVO.getIsVirtualHouse()){
			CoalitionHouseDomain houseManage=coalitionHouseDao.getCoalitionHouseByHouseNumber(searchVO.getHouseName());
			if(null!=houseManage && null!=searchVO.getHouseName() && searchVO.getHouseName().trim().length()>0){
				StringBuilder houseIds=new StringBuilder();
				houseIds.append(houseManage.getKeyword()).append(',');
				for(HouseDomain house : houseManage.getHouses()){
					houseIds.append(house.getKeyword()).append(',');
				}
				if(houseIds.charAt(houseIds.length()-1)==',')houseIds.deleteCharAt(houseIds.length()-1);
				searchVO.setHouseIds(houseIds.toString());
				searchVO.setHouseName(null);
			}
		}
	}

	/**
	 * 功能描述:生成收费通知单<br>
	 * @param userId
	 * Create author:罗军林<br>
	 * Create on:2008-9-25<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public Boolean buildNote(Long userId){
		Long startdate=System.currentTimeMillis();
		logger.info("开始生成通知单...");
		List<PeriodDomain> periodList=periodDao.findPeriodByValidity(SysrefcodeDO.FEE_PERIOD_VALIDITY_VALID);
		checkIsBuildNote(periodList);

		Date startTime=this.getDate();
		Map<Long,AbstractStaVersion> staVersionMap= chargeStaDao.queryVersionByChargeItem();
		Map<Long,ManageHouseBankBean> manageAccNumber=noteDao.queryManageAccNumber();

		for(PeriodDomain period : periodList){
			generateNote(userId, staVersionMap, manageAccNumber, period,null,false);
			savePeriodLog(userId,period,startTime);

			noteDao.flush();
			noteDao.clear();
		}

		logger.info("通知单生成完成,花费时间为："+(System.currentTimeMillis()-startdate));
		return true;
	}
	/***
	 * 生成催缴单
	 */
	public boolean buildReminderNote(Long userId){
		checkBuildReminderNote();
		Map<Long,AbstractStaVersion> staVersionMap= chargeStaDao.queryVersionByChargeItem();
		Map<Long,ManageHouseBankBean> manageAccNumber=noteDao.queryManageAccNumber();
		List<PeriodDomain> periodList=periodDao.findPeriodByValidity(SysrefcodeDO.FEE_PERIOD_VALIDITY_VALID);
		for(PeriodDomain period : periodList){
			generateNote(userId, staVersionMap, manageAccNumber, period,null,true);
			noteDao.flush();
			noteDao.clear();
		}
		return true;
	}

	/**
	 * 功能描述:检查能否生成通知单<br>
	 * @param periodList<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-10<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void checkIsBuildNote(List<PeriodDomain> periodList) {
		if(null==periodList || periodList.size()<=0){
			throw new BusinessException("charge:no_period_exception",BusinessException.ERROR);
		}
		for(PeriodDomain period : periodList){
			List<PeriodLogDomain> periodLogCalculates=periodLogDao.findLogByPeriodAndFlowDef(period.getKeyword(), SysrefcodeDO.FEE_FLOW_DEF_NAME_RECEIVABLE);
			if( null==periodLogCalculates || periodLogCalculates.size()<=0){
				throw new BusinessException("charge:no_calculate_exception,"+period.getPeriod(),BusinessException.WARNING);
			}

			List<PeriodLogDomain> periodLogNotes=periodLogDao.findLogByPeriodAndFlowDef(period.getKeyword(), SysrefcodeDO.FEE_FLOW_DEF_NAME_NOTICE);
			if( null!=periodLogNotes && periodLogNotes.size()>0){
				throw new BusinessException("charge:has_build_note_exception,"+period.getPeriod(),BusinessException.WARNING);
			}

			checkIsHasNewChargeDatas(period.getKeyword());
		}
	}

	/***
	 * 功能描述: 检查能否生成催缴单 <br>
	 * Create author:yandawei <br>
	 * Create on:2008-11-11  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void checkBuildReminderNote(){
		PeriodDomain period =  periodDao.queryCurrentPeriod();
		List<PeriodLogDomain> periodLogNotes=periodLogDao.findLogByPeriodAndFlowDef(period.getKeyword(), SysrefcodeDO.FEE_FLOW_DEF_NAME_NOTICE);
		if( null==periodLogNotes || periodLogNotes.size()==0){
			throw new BusinessException("charge:before_general_remindernote",BusinessException.WARNING);
		}
	}
	/**
	 * 功能描述:重新生成通知单<br>
	 * @param userId
	 * @param houseIds<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-25<br>
	 * Edit author:本次修改，在queryPeriodHouseIds的SQL中去除了两个检查逻辑：1）是否生成过通知单 2)是否有新建状态的数据
	 * ，本逻辑由后续的两个方法来完成。<br>
	 * Edit on:2008-11-4<br>
	 * Why:<br>
	 */
	public Boolean reBuildNote(Long userId,String houseIds) {
		if(null==houseIds){
			throw new BusinessException("charge:houseId_not_null",BusinessException.ERROR);
		}

		Map<Long,String> periodHouseIds= noteDao.queryPeriodHouseIds(houseIds);
		if(null==periodHouseIds || periodHouseIds.size()==0) throw new BusinessException("charge:house_has_no_period_exception",BusinessException.ERROR);

		List<PeriodDomain> periodList= periodDao.queryPeriodByIds(periodHouseIds.keySet());
		Map<Long,AbstractStaVersion> staVersionMap= chargeStaDao.queryVersionByChargeItem();
		Map<Long,ManageHouseBankBean> manageAccNumber=noteDao.queryManageAccNumber();

		for(PeriodDomain period : periodList){
			checkIsHasBuilder(period);
			checkIsHasNewChargeDatas(period.getKeyword());

			noteDao.blankOutNote(period.getKeyword(), period.getChargePrecinct().getKeyword(), periodHouseIds.get(period.getKeyword()));
			generateNote(userId, staVersionMap, manageAccNumber, period,periodHouseIds.get(period.getKeyword()),false);

			noteDao.flush();
			noteDao.clear();
		}

		return Boolean.TRUE;
	}


	/**
	 * 功能描述:重新生成全部通知单<br>
	 * @param userId
	 * Create author:罗军林<br>
	 * Create on:2008-9-25<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public Boolean reBuildNoteAll(Long userId) {
//		boolean isReBuild=noteDao.checkIsReBuildAll();
//		if(!isReBuild) throw new BusinessException("暂时不能做重新生成通知单");

		List<PeriodDomain> periodList= noteDao.queryIsBuildPeriodHQL();
		Map<Long,AbstractStaVersion> staVersionMap= chargeStaDao.queryVersionByChargeItem();
		Map<Long,ManageHouseBankBean> manageAccNumber=noteDao.queryManageAccNumber();

		for(PeriodDomain period : periodList){
			checkIsHasBuilder(period);
			checkIsHasNewChargeDatas(period.getKeyword());

			noteDao.blankOutNoteAll(period.getKeyword());
			generateNote(userId, staVersionMap, manageAccNumber, period,null,false);

			noteDao.flush();
			noteDao.clear();
		}

		return Boolean.TRUE;
	}


	/**
	 * 功能描述:检查是否有新建状态的原始数据<br>
	 * @param periodId<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-10<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void checkIsHasNewChargeDatas(Long  periodId) {
		List<ChargeDatasDomain> chargeDatas= meterDataRegisterDao.getMeterDatasListByPeriodId(periodId);
		if( null!=chargeDatas && chargeDatas.size()>0){
			HashSet<String> tempHouseNumber=new HashSet<String>();
			for(int i=0; i < chargeDatas.size();i++){
				tempHouseNumber.add(chargeDatas.get(i).getHouse().getHouseNumber());
			}
			throw new BusinessException("charge:house_has_new_data,"+reBuildHouseNumber(chargeDatas.size(), tempHouseNumber),BusinessException.FAILURE);
		}
	}

	/**
	 * 功能描述:将tempHouseNumber列表中的房号重新组织成用"、"隔开，如果超过chargeDataSizeException，则加"..."代替<br>
	 * @param chargeDatasSize
	 * @param tempHouseNumber
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-11-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private String reBuildHouseNumber(int chargeDatasSize, HashSet<String> tempHouseNumber) {
		StringBuffer houseIds=new StringBuffer();
		int index=0;
		for(String temp : tempHouseNumber){
			if(index>=chargeDataSizeException)break;
			houseIds.append(temp);
			if(index<chargeDataSizeException-1 && index<tempHouseNumber.size()-1){
				houseIds.append("、");
			}
			index++;
		}
		if(tempHouseNumber.size()>chargeDataSizeException){
			houseIds.append("……");
		}
		return houseIds.toString();
	}

	/**
	 * 功能描述:<br>
	 * @param userId
	 * @param staVersionMap
	 * @param manageAccNumber
	 * @param period
	 * @param houseIds<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-25<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void generateNote(Long userId, Map<Long, AbstractStaVersion> staVersionMap, Map<Long, ManageHouseBankBean> manageAccNumber, PeriodDomain period,String houseIds,boolean isReminder) {
		int pageNo=1;
		Map<Long,Long> manageHouseMap=noteDao.queryManageHouse(period.getChargePrecinct().getKeyword());
		List<ChargeDatasDomain> chargeDatasList=meterDataRegisterDao.queryLastMeterData(period.getKeyword());
		int noteCount=noteDao.getCountNote(period.getKeyword(),isReminder);
		List<TransrnoteNote> tranList=null;
		//通知单明细列表
		List<TransRNoteVO> transRnoteList=new ArrayList<TransRNoteVO>();
		//管理房通知单列表
		Map<Long,NoteDomain> manageHouseNoteMap=new HashMap<Long, NoteDomain>();
		Map<String,TransRNoteVO> manageTransRnotesMap=new HashMap<String, TransRNoteVO>();
		SysInfo currentSysinfo=createInfo(userId);//当前用户信息
		Map<Long,NoteDomain> noteMap=new HashMap<Long, NoteDomain>();//改动的
		do{
			tranList=noteDao.queryTran(period.getKeyword(),period.getChargePrecinct().getKeyword(),houseIds,pageNo,PAGESIZE);
//			Map<Long,NoteDomain> noteMap=new HashMap<Long, NoteDomain>();
			for(TransrnoteNote tran : tranList){
				//通知单
				NoteDomain noteDomain=noteMap.get(tran.getHouseId());
				if(noteDomain == null){
					noteDomain=saveNoteDomain(currentSysinfo, period,tran,++noteCount,isReminder);
					noteMap.put(tran.getHouseId(), noteDomain);
				}else{
					sumTotal(tran, noteDomain);
				}

				TransRNoteVO transRNote = saveTransRNote(staVersionMap, chargeDatasList, tran, noteDomain.getNoteId());
				transRnoteList.add( transRNote );

				//管理房
				Long manageHouseId=manageHouseMap.get(noteDomain.getHouse().getKeyword());
				if(manageHouseId!=null ){
					NoteDomain manageHouseNote = buildManageHouseNote(currentSysinfo, manageAccNumber, period, ++noteCount, manageHouseNoteMap, tran, noteDomain, manageHouseId,isReminder);

					buildManageHouseTransRNote(manageTransRnotesMap, tran.getChargeItemId(), transRNote, manageHouseNote,manageHouseId);
				}
			}
			pageNo++;
		}while(  tranList!=null && tranList.size()== PAGESIZE);

		transRnoteList.addAll(manageTransRnotesMap.values());
		noteDao.insertTransRNote(transRnoteList);
	}

	/**
	 * 功能描述:<br>
	 * @param manageTransRnotesMap
	 * @param tran
	 * @param transRNote
	 * @param manageHouseNote<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-24<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void buildManageHouseTransRNote(Map<String, TransRNoteVO> manageTransRnotesMap, Long chargeItemId, TransRNoteVO transRNote, NoteDomain manageHouseNote,Long manageHouseId) {
		TransRNoteVO manageHouseTransRNoteVO = manageTransRnotesMap.get(manageHouseId+","+chargeItemId);
		if(null==manageHouseTransRNoteVO){
			manageHouseTransRNoteVO=transRNote.clone();
			manageHouseTransRNoteVO.setNoteId(manageHouseNote.getNoteId());
			manageTransRnotesMap.put(manageHouseId+","+chargeItemId, manageHouseTransRNoteVO);
		}else if(null!=manageHouseTransRNoteVO){
			sumManageHouseTransRNote(transRNote, manageHouseTransRNoteVO);
		}
	}

	/** 功能描述:生成管理房的通知单<br>
	 * @param userId
	 * @param manageAccNumber
	 * @param period
	 * @param noteCount
	 * @param manageHouseNoteMap
	 * @param tran
	 * @param noteDomain
	 * @param manageHouseId
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-24<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private NoteDomain buildManageHouseNote(SysInfo currentSysinfo, Map<Long, ManageHouseBankBean> manageAccNumber, PeriodDomain period, int noteCount, Map<Long, NoteDomain> manageHouseNoteMap, TransrnoteNote tran, NoteDomain noteDomain, Long manageHouseId,boolean isReminder) {
		NoteDomain manageHouseNote=manageHouseNoteMap.get(manageHouseId);
		ManageHouseBankBean manageHouseBankBean= manageAccNumber.get(manageHouseId);
		if( manageHouseNote==null){
			manageHouseNote=saveManageHouseNote(currentSysinfo,period,noteDomain,manageHouseBankBean,++noteCount,isReminder);
			manageHouseNoteMap.put(manageHouseId, manageHouseNote);
		}else{
			sumTotal(tran,manageHouseNote);
		}
		return manageHouseNote;
	}

	/** 功能描述:生成管理房的通知单明细<br>
	 * @param transRNote
	 * @param manageHouseTransRNoteVO<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-24<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void sumManageHouseTransRNote(TransRNoteVO transRNote, TransRNoteVO manageHouseTransRNoteVO) {
		manageHouseTransRNoteVO.setOldAmt( addBigDecimal(manageHouseTransRNoteVO.getOldAmt(), transRNote.getOldAmt()));
		manageHouseTransRNoteVO.setThisAmt(addBigDecimal(manageHouseTransRNoteVO.getThisAmt(), transRNote.getThisAmt()));
		manageHouseTransRNoteVO.setTotalAmt(addBigDecimal(manageHouseTransRNoteVO.getTotalAmt(), transRNote.getTotalAmt()));
		manageHouseTransRNoteVO.setWastage(addBigDecimal(manageHouseTransRNoteVO.getWastage(), transRNote.getWastage()));
		manageHouseTransRNoteVO.setLastReading(addBigDecimal(manageHouseTransRNoteVO.getLastReading(), transRNote.getLastReading()));
		manageHouseTransRNoteVO.setThisReading(addBigDecimal(manageHouseTransRNoteVO.getThisReading(), transRNote.getThisReading()));
	}

	/**
	 * 功能描述:返回两数的和，如果有一项为NULL，则直接返回另一项<br>
	 * @param a
	 * @param b
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-24<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal addBigDecimal(BigDecimal a,BigDecimal b){
		if(null==a){
			return b;
		}else if(null==b){
			return a;
		}else{
			return a.add(b);
		}
	}


	private NoteDomain saveManageHouseNote(SysInfo currentSysinfo, PeriodDomain period, NoteDomain noteDomain,ManageHouseBankBean manageHouseBankBean,int noteCount,boolean isReminder){
		NoteDomain manageHouseNote=new NoteDomain();
		manageHouseNote.setAccNumber(manageHouseBankBean.getAccNumber());
		manageHouseNote.setChargePrecint(noteDomain.getChargePrecint());
		manageHouseNote.setClients(manageHouseBankBean.getClients());
		manageHouseNote.setHouse( houseDao.loadById(manageHouseBankBean.getManageHouseId()) );
		manageHouseNote.setHouseNumber(manageHouseBankBean.getHouseNumber());
		manageHouseNote.setHouseSize(noteDomain.getHouseSize());
		manageHouseNote.setOldAmtSum(noteDomain.getOldAmtSum());
		manageHouseNote.setPeriod(period);
		manageHouseNote.setProRight(proRightDao.loadById(manageHouseBankBean.getProRightId()));
		manageHouseNote.setReminder(isReminder == false ?SysrefcodeDO.FEE_NOTE_REMINDER_FALSE:SysrefcodeDO.FEE_NOTE_REMINDER_TRUE);
		manageHouseNote.setRequisitionNum(buildRequisitionNum(period, noteCount,isReminder));
		manageHouseNote.setSysInfo(currentSysinfo);
		manageHouseNote.setThisAmtSum(noteDomain.getThisAmtSum());
		manageHouseNote.setTotalAmt(noteDomain.getTotalAmt());
		manageHouseNote.setValidity(SysrefcodeDO.FEE_NOTE_VALIDITY_TRUE);
		noteDao.saveObject(manageHouseNote);

		return manageHouseNote;
	}



	/**
	 * 功能描述:保存帐期日志<br>
	 * @param userId
	 * @param period
	 * @param startTime<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-12<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void savePeriodLog(Long userId, PeriodDomain period, Date startTime) {
		PeriodLogDomain periodLog=new PeriodLogDomain();
		periodLog.setStartTime(startTime);
		periodLog.setEndTime(this.getDate());
		periodLog.setPeriod(period);
		periodLog.setCreator(userId);
		periodLog.setFlowDef(flowDefDao.findFlowDefBySEQ(SysrefcodeDO.FEE_FLOW_DEF_NAME_NOTICE));
		periodLogDao.saveObject(periodLog);
	}


	/**
	 * 功能描述:产生通知单明细<br>
	 * @param staVersionMap
	 * @param chargeDatas
	 * @param tran
	 * @param noteDomain
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private TransRNoteVO saveTransRNote(Map<Long, AbstractStaVersion> staVersionMap, List<ChargeDatasDomain> chargeDatas, TransrnoteNote tran, Long noteId) {
		AbstractStaVersion version=staVersionMap.get(tran.getChargeItemId());
		ChargeDatasDomain chargeData=getCurrentChargeDatas(tran.getHouseId(),chargeDatas, version);

		TransRNoteVO transRNoteVO=new TransRNoteVO();
		transRNoteVO.setNoteId(noteId);
		transRNoteVO.setChargeItemId(tran.getChargeItemId());
		transRNoteVO.setOldAmt(tran.getOldAmt());
		transRNoteVO.setTotalAmt(tran.getTotalAmt());
		transRNoteVO.setThisAmt(tran.getThisAmt());
		setNotePrices(version, transRNoteVO);
		setChargeDatasRead(tran.getHouseId(), version, chargeData, transRNoteVO);
		return transRNoteVO;
	}

	/**
	 * 功能描述:设置原始数据读数<br>
	 * @param houseId
	 * @param version
	 * @param chargeData
	 * @param transRNoteVO<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-30<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void setChargeDatasRead(Long houseId, AbstractStaVersion version, ChargeDatasDomain chargeData, TransRNoteVO transRNoteVO) {
		if(version==null){
			transRNoteVO.setThisReading( null );
			transRNoteVO.setLastReading( null );
			transRNoteVO.setWastage( null );
			return;
		}

		if(null != chargeData){
			transRNoteVO.setThisReading( chargeData.getThisReading() );
			transRNoteVO.setLastReading( chargeData.getLastReading() );
			transRNoteVO.setWastage( chargeData.getWastage() );
		}else if(BigDecimal.ZERO.compareTo(transRNoteVO.getTotalAmt())<0
				&& version.getChargeSta().getChargeItem().getMeterType()!=null){
			ChargeDatasDomain datas=meterDataRegisterDao.findLastMeterData(
					houseId, version.getChargeSta().getChargeItem().getMeterType());
			if(null!=datas){
				transRNoteVO.setThisReading( datas.getThisReading() );
				transRNoteVO.setLastReading( datas.getThisReading() );
				transRNoteVO.setWastage( BigDecimal.ZERO );
			}
		}
	}

	/**
	 * 功能描述:设置收费版本所对应的三个单价<br>
	 * @param version
	 * @param transRNoteVO<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-30<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void setNotePrices(AbstractStaVersion version, TransRNoteVO transRNoteVO) {
		if( null==version ){
			transRNoteVO.setPrice(null);
			transRNoteVO.setOverPrice1(null);
			transRNoteVO.setOverPrice2(null);
			return ;
		}
		if( null!=version.getPrice()){
			transRNoteVO.setPrice(version.getPrice());
			transRNoteVO.setOverPrice1(null);
			transRNoteVO.setOverPrice2(null);
		}else{
			transRNoteVO.setPrice( getOverPrice(version.getSecStas(),getFirstStartPoint(version.getSecStas())) );
			transRNoteVO.setOverPrice1(
					getOverPrice(version.getSecStas(), getSecondStartPoint(version.getSecStas())) );
			transRNoteVO.setOverPrice2(
					getOverPrice(version.getSecStas(), getThirdStartPoint(version.getSecStas())) );
		}
	}




	/**
	 * 功能描述:返回当前的原始数据<br>
	 * @param chargeDatas
	 * @param version
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private ChargeDatasDomain getCurrentChargeDatas(Long houseId,List<ChargeDatasDomain> chargeDatas, AbstractStaVersion version) {
		if(null==version)return null;
		for(ChargeDatasDomain item : chargeDatas){
			if(item.getHouse().getKeyword().equals(houseId) &&
					item.getMeter().getMeterType().getCode().equals(version.getChargeSta().getChargeItem().getMeterType())){
				return item;
			}
		}
		return null;
	}

	/**
	 * 功能描述:取得给定起点的超额单价,<br>
	 * @param sectStas
	 * @return
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal getOverPrice(Set<SectSta> sectStas,BigDecimal startPoint) {
		BigDecimal price=null;
		if(null==startPoint)return null;
		for(SectSta sect : sectStas){
			if( sect.getStartPoint().compareTo(startPoint)==0 ){
				price=sect.getPrice();
				break;
			}
		}
		return price;
	}


	/**
	 * 功能描述:取得第一个超额的起点<br>
	 * @param sectStas
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal getFirstStartPoint(Set<SectSta> sectStas) {
		List<SectSta> list= new ArrayList<SectSta>();
		list.addAll(sectStas);
		Collections.sort(list,PmsUtilityComparator.getComparator());
		return (null==list || list.size()<1) ? null : list.get(0).getStartPoint();
	}

	/**
	 * 功能描述:取得第二个超额的起点<br>
	 * @param sectStas
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal getSecondStartPoint(Set<SectSta> sectStas) {
		List<SectSta> list= new ArrayList<SectSta>();
		list.addAll(sectStas);
		Collections.sort(list,PmsUtilityComparator.getComparator());
		return (null==list || list.size()<2) ? null : list.get(1).getStartPoint();
	}

	/**
	 * 功能描述:取得第三个超额的起点<br>
	 * @param sectStas
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-22<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal getThirdStartPoint(Set<SectSta> sectStas) {

		List<SectSta> list= new ArrayList<SectSta>();
		list.addAll(sectStas);
		Collections.sort(list,PmsUtilityComparator.getComparator());
		return (null==list || list.size()<3) ? null : list.get(2).getStartPoint();
	}

	/**
	 * 功能描述:费用累计，这里累计本月合计、应收合计、往月欠款合计<br>
	 * @param tran
	 * @param noteDomain<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void sumTotal(TransrnoteNote tran, NoteDomain noteDomain) {
		noteDomain.setOldAmtSum(addBigDecimal(noteDomain.getOldAmtSum(), tran.getOldAmt()));
		noteDomain.setThisAmtSum(addBigDecimal(noteDomain.getThisAmtSum(), tran.getThisAmt()));
		noteDomain.setTotalAmt(addBigDecimal(noteDomain.getTotalAmt(), tran.getTotalAmt()));
	}

	/**
	 * 功能描述:<br>
	 * @param userId
	 * @param period
	 * @param noteMap
	 * @param tran<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private NoteDomain saveNoteDomain(SysInfo currentSysinfo, PeriodDomain period,TransrnoteNote tran,int noteCount,boolean isReminder) {
		NoteDomain noteDomain=new NoteDomain();
		noteDomain.setAccNumber(tran.getAccNumber());
		noteDomain.setChargePrecint(period.getChargePrecinct());
		noteDomain.setClients(tran.getClients());
		noteDomain.setHouse( houseDao.loadById(tran.getHouseId()) );
		noteDomain.setHouseNumber( tran.getHouseNumber() );
		noteDomain.setHouseSize( tran.getBuildSize() );
		noteDomain.setOldAmtSum( tran.getOldAmt() );
		noteDomain.setPeriod(period);
		noteDomain.setProRight( proRightDao.loadById(tran.getProRightId()) );
		noteDomain.setReminder( isReminder == false ?SysrefcodeDO.FEE_NOTE_REMINDER_FALSE:SysrefcodeDO.FEE_NOTE_REMINDER_TRUE);
		noteDomain.setRequisitionNum( buildRequisitionNum(period,noteCount,isReminder) );
		noteDomain.setSysInfo(currentSysinfo);
		noteDomain.setThisAmtSum( tran.getThisAmt() );
		noteDomain.setTotalAmt( tran.getTotalAmt() );
		noteDomain.setValidity( SysrefcodeDO.FEE_NOTE_VALIDITY_TRUE );
		noteDao.saveObject(noteDomain);
		return noteDomain;
	}


	/**
	 * 功能描述:生成流水号<br>
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private String buildRequisitionNum(PeriodDomain period,int noteCount,boolean isReminder){
		StringBuffer num=new StringBuffer();
		num.append(isReminder == false?REQUISITION_NOTE_NUMBER:REMINDER_NOTE_NUMBER).append(period.getChargePrecinct().getPrecinctCode().trim())
		.append("-").append(period.getPeriod().trim()).append("-");

		num.append(formatNum(noteCount));

		return num.toString();
	}

	/**
	 * 功能描述:<br>
	 * @param noteCount
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-28<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private String formatNum(int noteCount) {

		NumberFormat numberFormat=NumberFormat.getInstance();
		numberFormat.setMaximumIntegerDigits(5);
		numberFormat.setMinimumIntegerDigits(5);
		numberFormat.setGroupingUsed(false);

		return numberFormat.format(noteCount);
	}



	/**
	 * 功能描述:<br>
	 * @param page<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-17<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private List<NoteVO> convertDOtoVOList(List<NoteDomain> result) {
		List<NoteVO> temp=new ArrayList<NoteVO>();
		for(NoteDomain noteDomain : result){
			temp.add(convertDoToVO(noteDomain));
		}
		return temp;
	}

	/**
	 * 功能描述:<br>
	 * @param noteDomain<br>
	 * Create author:罗军林<br>
	 * Create on:2008-9-17<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private NoteVO convertDoToVO(NoteDomain noteDomain) {
		NoteVO noteVO=new NoteVO();
		if(null != noteDomain && null != noteDomain.getHouse() && null != noteDomain.getHouse().getBuilding()){
			noteVO.setBuildingId( noteDomain.getHouse().getBuilding().getKeyword());
			noteVO.setBuildingName(noteDomain.getHouse().getBuilding().getName());
		}
		noteVO.setHouseName(noteDomain.getHouseNumber());
		noteVO.setHouseId(noteDomain.getHouse().getKeyword());
		noteVO.setPeriod(noteDomain.getPeriod().getPeriod());
		noteVO.setPeriodId(noteDomain.getPeriod().getKeyword());
		noteVO.setNoteId(noteDomain.getNoteId());
		noteVO.setRequisitionNum(noteDomain.getRequisitionNum());
		noteVO.setTotalAmt(noteDomain.getTotalAmt());
		noteVO.setBuildDate(noteDomain.getSysInfo().getSysDate());
		noteVO.setValidity(noteDomain.getValidity());
		//是否是否催缴单
		noteVO.setReminder(noteDomain.getReminder());
		noteVO.setValidityStr( SysrefcodeDO.FEE_NOTE_VALIDITY_TRUE.equals(noteDomain.getValidity()) ? SysrefcodeDO.IS_ACTIVE :  SysrefcodeDO.IS_NOT_ACTIVE);
		return noteVO;
	}



	/**
	 * 功能描述:检查是否有生成通知单，如果没有则抛出异常<br>
	 * @param period<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-10<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void checkIsHasBuilder(PeriodDomain period) {
		List<PeriodLogDomain> periodLogNotes=periodLogDao.findLogByPeriodAndFlowDef(period.getKeyword(), SysrefcodeDO.FEE_FLOW_DEF_NAME_NOTICE);
		if( null==periodLogNotes || periodLogNotes.size()<=0){
			throw new BusinessException("charge:has_no_buildNote_exception,"+period.getPeriod(),BusinessException.WARNING);
		}
	}


	public void setChargeStaDao(IChargeStaDao chargeStaDao) {
		this.chargeStaDao = chargeStaDao;
	}

	public void setFlowDefDao(IFlowDefDao flowDefDao) {
		this.flowDefDao = flowDefDao;
	}

	public void setHouseDao(IHouseDao houseDao) {
		this.houseDao = houseDao;
	}

	public void setMeterDataRegisterDao(IMeterDataRegisterDao meterDataRegisterDao) {
		this.meterDataRegisterDao = meterDataRegisterDao;
	}

	public void setNoteDao(INoteDao noteDao) {
		this.noteDao = noteDao;
	}

	public void setPeriodLogDao(IPeriodLogDao periodLogDao) {
		this.periodLogDao = periodLogDao;
	}

	public void setProRightDao(IProRightDao proRightDao) {
		this.proRightDao = proRightDao;
	}

	public void setPeriodDao(IPeriodDao periodDao) {
		this.periodDao = periodDao;
	}

	public void setCoalitionHouseDao(ICoalitionHouseDao coalitionHouseDao) {
		this.coalitionHouseDao = coalitionHouseDao;
	}




}
